package com.cloud.school.app.config;


import com.cloud.school.app.config.security.JWTFilter;
import com.cloud.school.app.config.security.SecurityUserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import static com.cloud.school.app.config.security.SecurityUserUtils.LOGIN_USER;

/**
 * @ClassName WebSecurityConfiguration
 * @Description TODO
 * @Author 36297
 * @Date 2018/12/1 18:56
 * @Version 1.0
 */
@Slf4j
@EnableWebSecurity
@EnableConfigurationProperties(CloudSchoolProperties.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    public static final String ROLE_ADMIN = "ADMIN";
    public static final String ROLE_USER = "USER";

    @Autowired
    @Qualifier("userDetailsService")
    private UserDetailsService userDetailsService;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private CloudSchoolProperties cloudSchoolProperties;

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/swagger-ui.html")
                .antMatchers("/v2/**")
                .antMatchers("/webjars/**")
                .antMatchers("/resources/**")
                .antMatchers("/swagger-resources/**");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.cors().configurationSource(configurationSource()).and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().addFilterBefore(new JWTFilter(cacheService), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers(cloudSchoolProperties.getSecurity().getPermitPath()).permitAll()
                .antMatchers(cloudSchoolProperties.getSecurity().getAdminPath()).hasRole(ROLE_ADMIN)
                .antMatchers(cloudSchoolProperties.getSecurity().getUserpath()).hasAnyRole(ROLE_USER, ROLE_ADMIN)
                .anyRequest().authenticated()
                .and()
                .logout().logoutUrl("/user/logout").addLogoutHandler((q, p, a) -> cacheService.delete(LOGIN_USER + SecurityUserUtils.getCurrentUserPhoneNum()));
    }

    /**
     * @param
     * @Title: verificationCodeCache
     * @Description: 缓存手机验证码, 多节点部署需要替换成redis
     * @return: com.google.common.cache.Cache<java.lang.String                               ,                               java.lang.String>
     * @author: 36297
     * @date: 2018/12/2 21:00
     */
    /*@Bean
    public Cache<String, String> verificationCodeCache() {
        return CacheBuilder.newBuilder().concurrencyLevel(10).expireAfterWrite(65, TimeUnit.SECONDS).initialCapacity(10).maximumSize(100000).build();
    }*/
    @Override
    @Bean(name = "authenticationManager")
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * @Title: configurationSource
     * @Description: 设置跨域
     * @return: org.springframework.web.cors.CorsConfigurationSource
     */
    private CorsConfigurationSource configurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setMaxAge(3600l);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}
